const express = require('express')
const cors = require('cors')
const bodyParser = require('body-parser')
const { ipcMain } = require('electron')

class HttpServerManager {
  constructor() {
    this.app = null
    this.server = null
    this.routes = new Map()
    this.isRunning = false
    this.port = 3000
    this.mainWindow = null
  }

  setMainWindow(window) {
    this.mainWindow = window
  }

  async start(config) {
    if (this.isRunning) {
      return { success: false, error: 'Server already running' }
    }

    this.port = config.port || 3000

    try {
      // Create Express app
      this.app = express()
      
      // Middleware
      this.app.use(cors())
      this.app.use(bodyParser.json())
      this.app.use(bodyParser.urlencoded({ extended: true }))
      
      // Request logging middleware
      this.app.use((req, res, next) => {
        const startTime = Date.now()
        
        // Log after response
        res.on('finish', () => {
          const log = {
            timestamp: new Date().toISOString(),
            method: req.method,
            url: req.path,
            ip: req.ip || req.connection.remoteAddress || 'unknown',
            status: res.statusCode,
            responseTime: Date.now() - startTime,
            headers: req.headers,
            query: req.query,
            body: req.body
          }
          
          // Send log to renderer
          if (this.mainWindow && !this.mainWindow.isDestroyed()) {
            this.mainWindow.webContents.send('http-server:request-log', log)
          }
        })
        
        next()
      })
      
      // Dynamic route handler - use middleware instead of wildcard route
      this.app.use((req, res) => {
        const routeKey = `${req.method} ${req.path}`
        const routeData = this.routes.get(routeKey)
        
        if (routeData) {
          // Parse response data
          let responseData = routeData.data || routeData.response
          if (typeof responseData === 'string') {
            try {
              responseData = JSON.parse(responseData)
            } catch (e) {
              // Keep as string if not valid JSON
            }
          }
          
          // Parse headers
          let headers = routeData.headers
          if (typeof headers === 'string') {
            try {
              headers = JSON.parse(headers)
            } catch (e) {
              headers = { 'Content-Type': 'application/json' }
            }
          }
          
          // Set headers
          if (headers) {
            Object.entries(headers).forEach(([key, value]) => {
              res.setHeader(key, value)
            })
          }
          
          // Apply delay if specified
          const delay = routeData.delay || 0
          if (delay > 0) {
            setTimeout(() => {
              res.status(routeData.status || 200).send(responseData)
            }, delay)
          } else {
            res.status(routeData.status || 200).send(responseData)
          }
        } else {
          // Route not found
          res.status(404).json({
            error: 'Route not found',
            path: req.path,
            method: req.method,
            availableRoutes: Array.from(this.routes.keys())
          })
        }
      })
      
      // Start server
      return new Promise((resolve) => {
        this.server = this.app.listen(this.port, '0.0.0.0', () => {
          this.isRunning = true
          console.log(`HTTP Server started on http://0.0.0.0:${this.port}`)
          resolve({ 
            success: true, 
            message: `Server started on port ${this.port}`,
            url: `http://localhost:${this.port}`
          })
        })
        
        this.server.on('error', (err) => {
          console.error('Server error:', err)
          this.isRunning = false
          resolve({ success: false, error: err.message })
        })
      })
    } catch (err) {
      console.error('Failed to start server:', err)
      return { success: false, error: err.message }
    }
  }

  async stop() {
    if (!this.isRunning || !this.server) {
      return { success: false, error: 'Server not running' }
    }

    return new Promise((resolve) => {
      // Force close all connections
      this.server.close((err) => {
        if (err) {
          // Force destroy the server if normal close fails
          try {
            this.server.closeAllConnections()
          } catch (e) {
            console.error('Error forcing connection close:', e)
          }
        }
        
        this.isRunning = false
        this.app = null
        this.server = null
        this.routes.clear()
        console.log('HTTP Server stopped')
        resolve({ success: true, message: 'Server stopped' })
      })
      
      // Set a timeout to force close if it takes too long
      setTimeout(() => {
        if (this.server) {
          try {
            this.server.closeAllConnections()
          } catch (e) {
            console.error('Error in timeout close:', e)
          }
          this.isRunning = false
          this.app = null
          this.server = null
          this.routes.clear()
          console.log('HTTP Server force stopped')
          resolve({ success: true, message: 'Server force stopped' })
        }
      }, 2000)
    })
  }

  addRoute(route, response) {
    if (!route) return { success: false, error: 'Route is required' }
    
    this.routes.set(route, response)
    console.log(`Route added: ${route}`, response)
    
    return { success: true, message: `Route ${route} added` }
  }

  removeRoute(route) {
    if (!route) return { success: false, error: 'Route is required' }
    
    const deleted = this.routes.delete(route)
    console.log(`Route removed: ${route}`)
    
    return { success: deleted, message: deleted ? `Route ${route} removed` : `Route ${route} not found` }
  }

  getRoutes() {
    return Array.from(this.routes.keys())
  }
}

// Create singleton instance
const serverManager = new HttpServerManager()

// Setup IPC handlers
function setupHttpServerIPC(mainWindow) {
  serverManager.setMainWindow(mainWindow)
  
  ipcMain.handle('http-server:start', async (event, config) => {
    return await serverManager.start(config)
  })
  
  ipcMain.handle('http-server:stop', async () => {
    return await serverManager.stop()
  })
  
  ipcMain.handle('http-server:add-route', async (event, { route, response }) => {
    return serverManager.addRoute(route, response)
  })
  
  ipcMain.handle('http-server:remove-route', async (event, route) => {
    return serverManager.removeRoute(route)
  })
  
  ipcMain.handle('http-server:get-routes', async () => {
    return serverManager.getRoutes()
  })
}

module.exports = {
  setupHttpServerIPC,
  serverManager
}